﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Graphics3
{
    public partial class Form1 : Form
    {
        private enum Editing
        {
            Nothing,
            StartPoint,
            EndPoint,
            MiddlePoint
        };

        private IList<Line> lines;
        private Point? startPoint;
        private Line previewLine;
        private Line selectedLine;
        private Editing editingPoint;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lines = new List<Line>();
            startPoint = null;
            selectedLine = null;
            editingPoint = Editing.Nothing;
            deleteButton.Enabled = false;

            toolTip1.SetToolTip(this.selectRadioButton, "Select");
            toolTip1.SetToolTip(this.drawLineRadioButton, "Draw line");

        }

        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {   
            var thread = new Thread(new ThreadStart(colorDialogThread));
            thread.Start();
        }

        private void colorDialogThread()
        {
            if (colorDialog1.ShowDialog() == DialogResult.OK)
            {
                this.colorPanel.BackColor = colorDialog1.Color;
                if (selectedLine != null)
                {
                    selectedLine.Color = colorDialog1.Color;
                }
            }
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (drawLineRadioButton.Checked)
            {
                startPoint = new Point(e.X, e.Y);
            }
            else if (selectedLine != null)
            {
                var point = new Point(e.X, e.Y);

                if (point.IsColseTo(selectedLine.StartPoint))
                {
                    editingPoint = Editing.StartPoint;
                }
                else if (point.IsColseTo(selectedLine.EndPoint))
                {
                    editingPoint = Editing.EndPoint;
                }
                else if (point.IsColseTo(selectedLine.MiddlePoint))
                {
                    editingPoint = Editing.MiddlePoint;
                }
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (drawLineRadioButton.Checked)
            {
                if (startPoint.HasValue)
                {
                    lines.Add(new Line()
                        {
                            StartPoint = startPoint.Value,
                            EndPoint = new Point(e.X, e.Y),
                            Color = colorPanel.BackColor,
                            Thickness = thicnessTrackBar.Value,
                            Antialiasing = antialiasingCheckBox.Checked
                        });

                    startPoint = null;
                    previewLine = null;
                    pictureBox1.Invalidate();
                }
            }
            else if (selectedLine != null && editingPoint != Editing.Nothing)
            {
                editingPoint = Editing.Nothing;
            }
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            var graphics = e.Graphics;
            pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);

            foreach (var line in lines)
            {
                if (line == selectedLine)
                {
                    pictureBox1.Image = selectedLine.DrawAsSelected(graphics, new Bitmap(pictureBox1.Image));
                }
                else
                {
                    //line.Draw(graphics);
                    pictureBox1.Image = line.Draw(new Bitmap(pictureBox1.Image), pictureBox1.BackColor);
                }
            }

            if (previewLine != null)
                previewLine.Draw(graphics);
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (drawLineRadioButton.Checked)
            {
                if (startPoint.HasValue)
                {
                    var graphics = this.pictureBox1.CreateGraphics();

                    previewLine = Line.PreviewLine(startPoint.Value, new Point(e.X, e.Y));
                    pictureBox1.Invalidate();
                }
            }
            else if (selectedLine != null)
            {
                var point = new Point(e.X, e.Y);
                switch (editingPoint)
                {
                    case Editing.StartPoint:
                        selectedLine.StartPoint = point;
                        pictureBox1.Invalidate();
                        break;
                    case Editing.EndPoint:
                        selectedLine.EndPoint = point;
                        pictureBox1.Invalidate();
                        break;
                    case Editing.MiddlePoint:
                        var middlePoint = selectedLine.MiddlePoint;
                        var xdiff = point.X - middlePoint.X;
                        var ydiff = point.Y - middlePoint.Y;
                        selectedLine.StartPoint = new Point(selectedLine.StartPoint.X + xdiff, selectedLine.StartPoint.Y + ydiff);
                        selectedLine.EndPoint = new Point(selectedLine.EndPoint.X + xdiff, selectedLine.EndPoint.Y + ydiff);
                        pictureBox1.Invalidate();                        
                        break;
                }
            }
        }

        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            if (selectRadioButton.Checked)
            {
                var point = new Point(e.X, e.Y);
                selectedLine = lines.OrderBy(line => line.GetUniversalDistance(point)).FirstOrDefault();
                antialiasingCheckBox.Checked = selectedLine.Antialiasing;
                colorPanel.BackColor = selectedLine.Color;
                thicnessTrackBar.Value = selectedLine.Thickness;
                pictureBox1.Invalidate();
            }
        }

        private void drawLineRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            selectedLine = null;
            if (drawLineRadioButton.Checked)
            {
                deleteButton.Enabled = false;
            }
            else
            {
                deleteButton.Enabled = true;
            }
        }

        private void deleteButton_Click(object sender, EventArgs e)
        {
            if (selectedLine != null)
            {
                lines.Remove(selectedLine);
                pictureBox1.Invalidate();
            }
        }

        private void antialiasingCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (selectedLine != null)
            {
                selectedLine.Antialiasing = antialiasingCheckBox.Checked;
            }
        }

        private void thicnessTrackBar_ValueChanged(object sender, EventArgs e)
        {
            if (selectedLine != null)
            {
                selectedLine.Thickness = thicnessTrackBar.Value;
            }
        }
    }
}
